package br.unicamp.ic.inf300.arena.action.vendas;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;

import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.StreamingResolution;
import net.sourceforge.stripes.action.UrlBinding;
import net.sourceforge.stripes.action.Wizard;
import net.sourceforge.stripes.validation.LocalizableError;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidationError;

import org.apache.log4j.Logger;

import br.unicamp.ic.inf300.arena.action.ArenaActionBean;
import br.unicamp.ic.inf300.arena.facade.FacadeFactory;
import br.unicamp.ic.inf300.arena.modelo.pessoa.Espectador;
import br.unicamp.ic.inf300.arena.modelo.pessoa.Estudante;
import br.unicamp.ic.inf300.arena.modelo.pessoa.Profissional;
import br.unicamp.ic.inf300.arena.modelo.pessoa.TipoEspectador;
import br.unicamp.ic.inf300.arena.modelo.vendas.Bilhete;
import br.unicamp.ic.inf300.arena.modelo.vendas.BilheteInteiro;
import br.unicamp.ic.inf300.arena.modelo.vendas.CartaoCredito;
import br.unicamp.ic.inf300.arena.modelo.vendas.Pagamento;
import br.unicamp.ic.inf300.arena.modelo.vendas.Venda;

@Wizard(startEvents="adicionarEspectador")
@UrlBinding("/vendas/VenderBilhetes.action")
public class VenderBilhetesActionBean extends ArenaActionBean {
	private static Logger _logger = Logger
			.getLogger( VenderBilhetesActionBean.class.getName() );

	private String targetUrl;

	//-- [ propriedades relacionadas aos campos do PASSO I do JSP vendaOnline ]
	private String docto;
	private Integer tipoEspectador;

	//-- [ propriedades relacionadas aos campos do PASSO II do JSP vendaOnline ]
	@Validate(required=true)
	private String formaPagto;

	@Validate(required=true, minlength=7, maxlength=7)
	private String numCartao;

	@Validate(required=true, minlength=4, maxlength=10)
	private String senha;

	@Validate(required=true, minlength=4, maxlength=5)
	private String codigoSeguranca;

	//-- metodos PUBLIC
    /**
     * Representa o PASSO II do processo de venda de bilhetes, indentificacao de espectadores.
     *
     * @return Resolution
     */
	@DefaultHandler
	public Resolution adicionarEspectador() {
    	_logger.debug("\n [[[[[ adicionarEspectador() ]]]]]\n\n" );

    	String msgToView = " ";
    	Espectador espectador = null; 

    	if ( TipoEspectador.ESTUDANTE.equals( TipoEspectador.get( tipoEspectador ) ) ) {
    		espectador = new Estudante(docto);
    	}
    	else {
    		espectador= new Profissional(docto);
    	}

    	IdentificacaoEspectadoresManagerBean mbean = null;
    	mbean = getContext().getIdentificacaoEspectadoresManagerBean();

    	if ( mbean.adicionar(espectador) ) {
    		msgToView = String.valueOf( mbean.total() ) + formataMsgAdicaoEspectador( mbean );
    	}

    	return new StreamingResolution("text", new StringReader( msgToView ));
    }

	/**
	 * 
	 * @return Resolution
	 *  
	 * @throws IOException
	 */
	public Resolution efetivarVenda() throws IOException {
		_logger.debug("\n [[[[[ efetivarVenda() ]]]]]\n\n" );

		Venda venda = null;
		Collection<Bilhete> bilhetes = null;
		Pagamento pagamento = null;

		try {
			bilhetes = gerarBilhetes();

			//na pratica para o modulo de pagamentos (subsistema) as consistencias sao feitas
			//apenas com base no num. do cartao para efeito de simplificacao
			pagamento = new CartaoCredito( Long.valueOf( numCartao ) );

			//camada de aplicacao (ActionBeans) utiliza recursos da camada de negocio (modelo)
			//a partir da abstracao de um servico, neste caso ITransacaoVendaServico
			venda = FacadeFactory.criarServicoTransacaoVenda().efetivarTransacao(bilhetes, pagamento);
			
			getContext().setVenda(venda);
		}
		catch (Exception e) {
			_logger.debug("\nEXCEPTION: " + e.getMessage() );
			System.err.println(e);

            //MSG de erro a ser exibida na JSP vendaOnline 
			ValidationError error = new LocalizableError("transacaoVendaNOTOK");
            getContext().getValidationErrors().add("venda", error);

            return getContext().getSourcePageResolution();
		}

		return new ForwardResolution("/resultadoVenda.jsp");
	}

	//-- metodos PRIVATE
	/**
	 * A partir da entrada de dados no JSP vendaOnline, instancia bilhetes {Meia-entrada, Entrada-inteira}
	 * parcialmente populados.
	 * 
	 * Os espectadores identificados sao usados como base para criacao de bilhetes.
	 *
	 * @return Bilhetes
	 *
	 */
	private Collection<Bilhete> gerarBilhetes() {
		Bilhete bilhete = null;
		Collection<Bilhete> bilhetes = new ArrayList<Bilhete>();

		Collection<Espectador> espectadores = null;

		//	ArenaActionBeanContext -> IdentificacaoEspectadoresManagerBean -> [Espectador1, Espectador2, ..]  
		espectadores = getContext().getIdentificacaoEspectadoresManagerBean().getEspectadores();

		for (Espectador espectador : espectadores) {
			bilhete = new BilheteInteiro();

			bilhete.setEspectador( espectador );
			bilhete.setEvento( getContext().getEventoSelecionado() );

			bilhetes.add(bilhete);

			_logger.debug("\n\n***** valor calculado p/ o bilhete gerado: "
					+ bilhete.toString() + "\n\n");
		}
		return bilhetes;
	}

	/**
	 * Formata MSG conforme eh adicionado 1 espectador no processo de venda de bilhete(s) p/ 1 evento
	 */
	private String formataMsgAdicaoEspectador(IdentificacaoEspectadoresManagerBean mbean) {
		StringBuffer msg = new StringBuffer();
		msg.append(" ");

		Collection<Espectador> espectadores = mbean.getEspectadores();

		if ( espectadores != null && espectadores.size() > 0 ) {
			msg.append(" adicionados, <u>&uacute;ltima adi&ccedil;&atilde;o</u>: ");
			msg.append( (docto != null ? docto : "") + ", ");
			msg.append( TipoEspectador.get( tipoEspectador ).getDescricao() );
		}
		return msg.toString();
	}

    //-- getters & setters
	/** The URL the user was trying to access. */
    public String getTargetUrl() { return targetUrl; }
    public void setTargetUrl(String targetUrl) { this.targetUrl = targetUrl; }

	public String getDocto() { return this.docto; }
	public void setDocto(String docto) {
		this.docto = docto;
	}

	public Integer getTipoEspectador() {
		return tipoEspectador;
	}
	public void setTipoEspectador(Integer tipoEspectador) {
		this.tipoEspectador = tipoEspectador;
	}

	public String getFormaPagto() {
		return formaPagto;
	}
	public void setFormaPagto(String formaPagto) {
		this.formaPagto = formaPagto;
	}

	public String getNumCartao() {
		return numCartao;
	}
	public void setNumCartao(String numCartao) {
		this.numCartao = numCartao;
	}

	public String getSenha() {
		return senha;
	}
	public void setSenha(String senha) {
		this.senha = senha;
	}

	public String getCodigoSeguranca() {
		return codigoSeguranca;
	}
	public void setCodigoSeguranca(String codigoSeguranca) {
		this.codigoSeguranca = codigoSeguranca;
	}
}